home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
batchut
/
test.zip
/
TEST.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-14
|
8KB
|
277 lines
/*
* MS-DOS Batch utility - test file/directory status
*
* Unix-like test program returns true or false according
* to a conditional expression.
*
* syntax: test <expression>
*
* test evaluates the expression <expression> and, if its value
* is true, returns a non-zero (true) exit status; otherwise, a
* zero (false) exit status is returned. test returns a
* zero if there are no arguments.
* The following primitives are used to construct an expression.
*
* primitive operators testing one file:
*
* -f|b|c|e|d|s|z|r|w|x filename
*
* -e true if filename exists
* -b true if filename exists and is a block special device
* -c true if filename exists and is a character special device
* -d true if filename exists and is a directory
* -f true if filename exists and is a regular file
* -s true if filename exists and has a size greater than zero
* -z true if filename exists and has a zero length (empty)
* -r true if filename exists and is readable
* -w true if filename exists and is writable
* -x true if filename exists and is executable
* (MS-DOS: file extension = .COM, .EXE, .BAT, or .BTM )
*
* -m[n] filename
* True if filename exists and has been modified in n days (default=1).
*
* primitive operators comparing two files:
*
* -D|N|S file1 file2
*
* -D true of file1 has same date as file2 and both files exist
* -N true if file1 is newer than file2 and both files exist
* -S true if file1 has same size as file2 and both files exist
*
* Logical operators:
*
* The above primitives may be combined with the following operators:
*
* cond1 [-a] cond2 True if both cond1 and cond2 are true.
* The -a is not required. It is implied by
* the juxtaposition by the two conditions.
*
* cond1 -o cond2 True if either cond1 or cond2 is true
* (-o is the OR operator).
*
* ! condition True if the condition is false
* (! is the unary NOT operator).
*
* AND/OR/NOT operators are processed left to right with no precedence;
* e.g. "! c1 -o c2 -a c3" is evaluated as (!c1 -o c2) -a c3.
*
*
* return errorlevel = 1 if the tested expression is true
* otherwise return 0 (conditions not meet or error flag set).
*
*****************************************************************************
*
* Developed by Jason Mathews, NASA/Goddard Space Flight Center
* <mathews@nssdca.gsfc.nasa.gov>
*
* Copyright (C) 1992-94 by Jason Mathews. Permission is granted to any
* individual or institution to use, copy or redistribute this software so long
* as it is not sold for profit, provided this copyright notice is retained.
*
* Modification history:
* 11/17/92 - Basic file & logical operators of UNIX test command.
* 11/28/92 - Added binary operator -N file1 file2 to test if
* file1 is newer than file2 by comparing the time stamp,
* added -n testing if a file has been modified in n days.
* 4/30/93 - Added 'S' file size equal operator.
* 4/14/94 - Added 'D' file date equal operator.
*
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#ifdef __MSDOS__
#include <string.h>
#endif
#ifdef unix
#define bool unsigned char
#else
typedef unsigned char bool;
#endif
#define true 1
#define false 0
int main (int argc, char**argv)
{
int rc, i = 1;
int count = 0; /* number of expressions evaluated */
bool newCond; /* new condition */
bool cond = true; /* start with return condition as false
* and set to true only if expression is true
*/
bool notFlag = false; /* NOT operator */
bool orFlag = false; /* OR operator */
char sw_char; /* switch character */
long value;
struct stat statbuf, statbuf2;
if (argc < 2) return 0; /* no arguments */
do
{
newCond = true; /* assume condition is true and
* set false only if condition is false.
*/
if (*argv[i] == '!')
{
notFlag = true;
i++;
}
if (argc - i < 2)
{
expect_arg:
fprintf(stderr, "test: argument expected\n");
return 0;
}
if (*argv[i] != '-')
{
sw_char = *argv[i];
unknown_arg:
fprintf(stderr, "test: unknown argument %c\n", sw_char);
return 0;
}
sw_char = argv[i][1];
switch (sw_char) {
case 'a':
orFlag = false; /* reset orFlag to false */
i++; /* move to next argument */
/* if (!count) cond = true; */ /* default */
continue; /* get next argument */
case 'o':
orFlag = true;
/* if first expression then start as false */
if (!count) cond = false;
i++;
continue;
} /* switch */
rc = stat( argv[i+1], &statbuf );
/* binary operator - check if 2nd argument exists */
if (sw_char=='N' || sw_char=='S' || sw_char=='D')
{
if (++i+1 >= argc || *argv[i+1]=='-') goto expect_arg; /* error */
rc |= stat(argv[i+1], &statbuf2);
}
if ( rc==0 ) /* file exists? */
switch (sw_char) {
case 'N': /* true if filename1 is newer than filename2 and both exist */
if (statbuf.st_mtime <= statbuf2.st_mtime) /* not newer? */
newCond = false;
break;
case 'S': /* true if filename1 is same size as filename2 and both exist */
if (statbuf.st_size != statbuf2.st_size)
newCond = false;
break;
case 'D': /* true if file1 has same date as file2 and both exist */
if (statbuf.st_mtime != statbuf2.st_mtime)
newCond = false;
break;
case 'm': /* true if filename exists and has been modified in n days */
/* also true if the time stamp is newer than the system clock */
value = (argv[i][2]) ? value = atol(argv[i]+2) : 1;
/* false if the time difference is greater than n days */
if ((time(0) - statbuf.st_mtime) > (86400L * value))
newCond = false;
break;
case 'd': /* true if filename exists and is a directory */
if (!(statbuf.st_mode & S_IFDIR)) newCond = false;
break;
case 'f': /* true if filename exists and is a regular file */
if (!(statbuf.st_mode & S_IFREG)) newCond = false;
break;
case 's': /* true if filename exists and has a size greater than zero */
if (statbuf.st_size == 0) newCond = false;
break;
case 'z': /* true if filename exists and has a zero length (empty) */
if (statbuf.st_size > 0) newCond = false;
break;
#ifndef __MSDOS__ /* always true for MS-DOS */
case 'r': /* true if filename exists and is readable */
if (!(statbuf.st_mode & S_IREAD)) newCond = false;
break;
#endif
case 'w': /* true if filename exists and is writable */
if (!(statbuf.st_mode & S_IWRITE)) newCond = false;
break;
/* Executable flag is only true for directories in MS-DOS.
* However, it should return true only if the file extension is
* .EXE, .COM, .BAT, or .BTM
*/
case 'x': /* true if filename exists and is executable */
#ifdef __MSDOS__
{
char *filename = argv[i+1];
while (*filename && *filename != '.') filename++;
strlwr(filename);
if (strcmp(filename, ".exe") && strcmp(filename, ".com") &&
strcmp(filename, ".bat") && strcmp(filename, ".btm"))
newCond = false;
}
#else
if (!(statbuf.st_mode & S_IEXEC)) newCond = false;
#endif
break;
case 'b': /* true if filename exists and is a block special device */
if (!(statbuf.st_mode & S_IFBLK)) newCond = false;
break;
case 'c': /* true if filename exist and is a character special device */
if (!(statbuf.st_mode & S_IFCHR)) newCond = false;
break;
case 'e': /* true if filename exists */
break;
default:
goto unknown_arg;
} /* switch */
else /* rc!=0: filename doesn't exist, so file condition is false */
{
newCond = false;
}
if (notFlag)
{
newCond ^= 1; /* toggle condition true/false */
notFlag = false; /* reset not flag for next condition */
}
if (orFlag)
{
/* if the condition is true then update condition to true. */
if (newCond) cond = true;
orFlag =